#include "StdAfx.h"
#include "Window.h"

CWindow::~CWindow()
{
	Unrealize();
}

LPCTSTR
CWindow::GetClassName()
{
	return GetName();
}

LPCTSTR
CWindow::GetWindowName()
{
	return GetName();
}

bool
CWindow::Realize(HINSTANCE hInstance)
{
	if (m_bIsRealized) {
		return false;
	}

	WNDCLASS wc;
	wc.style = 0;
	wc.lpfnWndProc = WindowProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = NULL;
	wc.hCursor = NULL;
	wc.hbrBackground = (HBRUSH)::GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = GetClassName();

	::RegisterClass(&wc);

	m_iWindowWidth = 800;
	m_iWindowHeight = 480;

	DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;

	RECT rc = { 0, 0, m_iWindowWidth, m_iWindowHeight };

	::AdjustWindowRect(&rc, dwStyle, FALSE);

	m_hWnd = ::CreateWindow(GetClassName(),
							GetWindowName(),
							dwStyle,
							0, 0,
							rc.right - rc.left,
							rc.bottom - rc.top,
							NULL, NULL, hInstance, NULL);


	if (!m_hWnd) {
		return false;
	}

	::ShowWindow(m_hWnd, SW_SHOW);
	::SetActiveWindow(m_hWnd);

	if (!Initialize()) {
		goto __FAIL;
	}

	m_bIsRealized = true;

	return true;

__FAIL:
	Unrealize();
	return false;
}

void
CWindow::Unrealize()
{
	Terminate();

	if (m_hWnd) {
		::DestroyWindow(m_hWnd);
		m_hWnd = NULL;
	}

	m_bIsRealized = false;
}


void
CWindow::Update()
{
	if (!m_bIsRealized) {
		return;
	}

	::UpdateWindow(m_hWnd);
}

int
CWindow::Run(HINSTANCE hInstance,
			  HINSTANCE hPrevInstance,
			  LPTSTR lpCmdLine,
			  int nCmdShow)
{
	if (hPrevInstance) {
		return 0;
	}

	if (!Realize(hInstance)) {
		return 0;
	}

	MSG msg;
	while (::GetMessage(&msg, NULL, 0, 0)) {
		::TranslateMessage(&msg);
		::DispatchMessage(&msg);
	}

	return msg.wParam;
}

void
CWindow::Quit()
{
	::PostMessage(m_hWnd, WM_CLOSE, 0, 0);
}

LPCTSTR
CWindow::GetName()
{
	return _T("DefaultWindow");
}

bool
CWindow::Initialize()
{
	return true;
}

void
CWindow::Terminate()
{
}

void
CWindow::Display()
{
}

void
CWindow::KeyDown(WPARAM wVirtualKeyCode,
				 LPARAM lKeyData)
{
	switch (wVirtualKeyCode) {
	case VK_ESCAPE:
		Quit();
		break;
	case VK_UP:
		KeyCtrl(KEYCTRL_UP);
		break;
	case VK_DOWN:
		KeyCtrl(KEYCTRL_DOWN);
		break;
	case VK_LEFT:
		KeyCtrl(KEYCTRL_LEFT);
		break;
	case VK_RIGHT:
		KeyCtrl(KEYCTRL_RIGHT);
		break;
	case VK_PRIOR:
		KeyCtrl(KEYCTRL_ZOOMOUT);
		break;
	case VK_NEXT:
		KeyCtrl(KEYCTRL_ZOOMIN);
		break;
	case 'S':
		KeyCtrl(KEYCTRL_DEMO_START);
		break;
	case 'E':
		KeyCtrl(KEYCTRL_DEMO_END);
		break;
	}
}

void
CWindow::KeyUp(WPARAM wVirtualKeyCode,
			   LPARAM lKeyData)
{
}

/** Example application instance.
 *
 */
CWindow* g_pWindow = NULL;

/** Window procedure.
 *
 */
LRESULT CALLBACK
WindowProc(HWND hWnd,
			UINT uMsg,
			WPARAM wParam,
			LPARAM lParam)
{
	switch (uMsg) {
	case WM_CLOSE:
		g_pWindow->Unrealize();
		return 0;
	case WM_DESTROY:
		::PostQuitMessage(0);
		return 0;
	case WM_PAINT:
		g_pWindow->Display();
		::ValidateRect(hWnd, NULL);
		return 0;
	case WM_KEYDOWN:
		g_pWindow->KeyDown(wParam, lParam);
		return 0;
	case WM_KEYUP:
		g_pWindow->KeyUp(wParam, lParam);
		return 0;
	}

	return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

